/*
 * button.cpp
 *
 *  Created on: 08 Apr 2011
 *      Author: wouter
 */
#include "port.h"
#include "avrlibdefs.h"

#define PIN_ADR			(this->pinAdr)
#define DDR_ADR			(this->pinAdr+1)
#define PORT_ADR		(this->pinAdr+2)

static inline u08 swap_bits(u08 n);

Cport::Cport(ePORT portNumber, ePinDir dir, bool pullup, bool swap) {
	this->pinAdr = 0x20 + ((portNumber - 1) * 3);
	this->swapFlag = swap;
	if (dir == ePinIn) {
		(*(volatile u08*) (DDR_ADR)) = 0;
	} else {
		(*(volatile u08*) (DDR_ADR)) = 1;
	}
	// If the pullup needs to be on configure it.
	if (pullup) {
		(*(volatile u08*) (PORT_ADR)) = 1;
	} else {
		(*(volatile u08*) (PORT_ADR)) = 0;
	}
}

void Cport::write(u08 dat) {
	if (swapFlag) {
		(*(volatile u08*) (PORT_ADR)) = swap_bits(dat);
	} else {
		(*(volatile u08*) (PORT_ADR)) = dat;
	}
}

u08 Cport::read(void) {
	u08 dat;
	dat = (*(volatile u08*) (PIN_ADR));
	if (swapFlag) {
		return swap_bits(dat);
	} else {
		return dat;
	}
}

static inline u08 swap_bits(u08 n) {
	n = ((n & 0xF0) >> 4) | ((n & 0x0F) << 4);
	n = ((n & 0xCC) >> 2) | ((n & 0x33) << 2);
	n = ((n & 0xAA) >> 1) | ((n & 0x55) << 1);
	return n;
}
